﻿namespace HuwmanCode.ServiceProcess.DebugSupport

open System
open System.Diagnostics
open System.IO
open System.IO.Pipes
open System.Runtime.InteropServices
open System.Security.Principal
open System.Threading
open System.Reflection
open System.ComponentModel.Composition
open HuwmanCode
open HuwmanCode.IO.Pipes
open HuwmanCode.Diagnostics.Logging
open HuwmanCode.ServiceProcess
open HuwmanCode.Diagnostics

[<Export(typeof<INotifyAttacher>)>]
type internal AttacherCooperator() =
    interface INotifyAttacher with
        member this.NotifyAttacher serviceProcess =
            let connect = async {
                try
                    use namedPipeServer = new NamedPipeServerStream(Assembly.GetEntryAssembly().FullName, PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous)
                    do! namedPipeServer.AsyncWaitForConnection()

                    let pipeWriter = new StreamWriter(namedPipeServer)
                    pipeWriter.WriteLine(serviceProcess.Id) //Send the id of the service process that the debugger should attach to
                    pipeWriter.Flush ()
                    namedPipeServer.WaitForPipeDrain()

                    let pipeReader = new StreamReader(namedPipeServer)
                    pipeReader.ReadLine() |> ignore  //Wait for the attach, the attacher will send a new line and release this blocking call when the attach is complete
                with _ -> () } 

            try
                Async.RunSynchronously(connect, timeout=5000) //We wait a maximum of 5 sec for an attach to occur. When a product is deployed this library should be excluded and this delay won't occur!
            with 
            | :? TimeoutException -> ()
            | _ -> Debugger.Launch() |> ignore
